package com.gframework.mybatis.util.generator.core.type;

import java.math.BigDecimal;
import java.sql.JDBCType;
import java.sql.Types;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.util.Date;

/**
 * Jdbc类型与Java类型相互转换核心处理操作类.<br>
 * <p>
 * 你可以通过本类将一个标准的jdbc类型转换成对应的java类型。
 * </p>
 * <p>
 * 你需要提供的是jdbc类型编号，根据jdbc标准，通过JdbcType类取得正确的数据类型。
 * 同时根据精度进行微小的调整，返回以以个更加合适的类型
 * </p>
 * 
 * @since 1.0.0
 * @author Ghwolf
 * 
 * @see JDBCType
 * @see Types
 */
public class JdbcTypeConversion {
	/**
	 * 将一个jdbc类型转换为Java类型.<br>
	 * 
	 * @param jdbcType JDBC类型编号{@link JDBCType}
	 * @param onlyCommonTypes 是否仅使用常用类型，如果为true，则不会出现byte、short、float、类型，而是采用Integer和Double代替。
	 * @return 返回最为合适的Java类型的Class类对象
	 * 
	 * @see JDBCType
	 * @see Types
	 */
	public static Class<?> convert(int jdbcType,boolean onlyCommonTypes) {
		return convert(jdbcType,-1,-1,onlyCommonTypes);
	}
	
	/**
	 * 将一个jdbc类型转换为Java类型.<br>
	 * 
	 * @param jdbcType JDBC类型编号{@link JDBCType}
	 * @param size 长度/精度
	 * @param decimalDigits 小数位精度
	 * @param onlyCommonTypes 是否仅使用常用类型，如果为true，则不会出现byte、short、float、类型，而是采用Integer和Double代替。
	 * @return 返回最为合适的Java类型的Class类对象
	 * 
	 * @see JDBCType
	 * @see Types
	 */
	public static Class<?> convert(int jdbcType,int size,int decimalDigits,boolean onlyCommonTypes) {
		JDBCType type ;
		try {
			type = JDBCType.valueOf(jdbcType);
		} catch(IllegalArgumentException e) {
			throw new UnknowJdbcTypeException("未知的JDBC类型[" + jdbcType + "]。");
		}
		switch (type) {
			case BIT:
				return Boolean.class;
			case TINYINT:
				return onlyCommonTypes ? Integer.class : Byte.class;
			case SMALLINT:
				return onlyCommonTypes ? Integer.class : Short.class;
			case INTEGER:
				return Integer.class;
			case BIGINT:
				return Long.class;
			case FLOAT:
				return Double.class;
			case REAL:
				return onlyCommonTypes ? Double.class : Float.class;
			case DOUBLE:
				return Double.class;
			case NUMERIC: 
			case DECIMAL: {
				if (size > 0 && size < 19 && decimalDigits == 0) {
					if (size >= 10) {
						return Long.class;
					} else {
						return Integer.class;
					}
				} else {
					return BigDecimal.class;
				}
			}
			case CHAR:
			case VARCHAR:
			case LONGVARCHAR:
				return String.class;
			case DATE:
			case TIME:
			case TIMESTAMP:
				return Date.class;
			case BINARY:
			case VARBINARY:
			case LONGVARBINARY:
				return byte[].class;
			case NULL: 
			case OTHER:
			case JAVA_OBJECT: 
			case DISTINCT: 
			case STRUCT:
			case ARRAY: 
				return Object.class;
			case BLOB:
				return byte[].class;
			case CLOB:
				return String.class;
			case REF:
			case DATALINK:
				return Object.class;
			case BOOLEAN:
				return Boolean.class;
			// case ROWID: 暂未知处理方式
			case NCHAR:
			case NVARCHAR:
			case LONGNVARCHAR:
			case NCLOB:
				return String.class;
			// case SQLXML: 暂未知处理方式
			// case REF_CURSOR: 暂未知处理方式
				
			// JDK1.8 TYPE
			case TIME_WITH_TIMEZONE:
				return OffsetTime.class;
			case TIMESTAMP_WITH_TIMEZONE:
				return OffsetDateTime.class;
			default:
				throw new UnknowJdbcTypeException("未知的JDBC类型[" + JDBCType.valueOf(jdbcType) + "]。");
		}
	}

	// prevent instance
	private JdbcTypeConversion() {
	}
}
